<?php
/**
 * Manadges comments to pages.
 *
 * @author Martin "DevelX" Jurča
 */
class Comments extends Module {
    protected $name = 'Comments';
    protected $administrable = true;
    protected $version = '2010-08-18';
    protected $system = false;
    protected $details = array('dependencies' => array(),
            'observes' => array('Comments'));

    const COMMENTS = 'comments';

    private $commentsTable = array('id' => 'iPN+', 'url' => "v'1000'I",
            'user' => 'iN', 'added' => 'iN', 'title' => "v'512'", 'text' =>
            "v'4096'");

    private $commentsRecord = array('table' => self::COMMENTS, 'data' =>
            array());

    public function __construct(DBAPI $dbapi, RecordList $recordList) {
        parent::__construct($dbapi, $recordList);
        $this->commentsRecord['properties'] = $this->commentsTable;
    }

    public function install() {
        Modules::getModule('Users')->registerRights('Comments',
                $this->getRights());
        return $this->dbdriver->createTable(self::COMMENTS,
                $this->commentsTable);
    }

    public function uninstall() {
        return $this->dbdriver->dropTable(self::COMMENTS);
    }

    public function initDisplay($param = null) {}

    public function getMetaInfo($property, $url) {
        $url = explode('/', $url);
        if (isset($url[1])) {
            if ($url[1] == 'add') {
                return 'Udělit komentář uživateli';
            } elseif ($url[1] == 'list') {
                return 'Získané komentáře';
            } elseif ($url[1] == 'posted') {
                return 'Udělené komentáře';
            }
        }
        return 'Komentáře';
    }

    public function display($param = null) {
        if (Kernel::getMode() == Kernel::ADMIN) {
            $this->displayAdmin($param);
        } else {
            $this->displayPublic($param);
        }
    }

    public function getCommentsCountOnUrl($url) {
        $cols = array('COUNT(*)');
        $count = &$this->dbdriver->select(self::COMMENTS, $cols, '`url` = \'' .
                $this->dbdriver->escapeString($url) . '\'');
        return $count[0]['COUNT(*)'];
    }

    public function &onAddComment(&$details, $source) {
        $result = null;
        if (!$this->hasRights('add comment')) {
            Modules::getModule('View')->addMessage($this->lang('noRightAdd'),
                    View::MSG_ERROR);
            return $result;
        }
        $user = &Modules::getModule('Users')->getUser();
        $comment = $this->commentsRecord;
        $comment['data'] = array('url' => $this->dbdriver->escapeString(
                $details['url']), 'user' => $user['data']['id'], 'added' =>
                time(), 'title' => $details['title'], 'text' =>
                $details['text']);
        $this->dbapi->save($comment);
        Kernel::setRedirect(str_replace('//', '/', Config::WEB_DIR . '/' .
                $details['url'] . '/'));
        return $result;
    }

    public function &onDelete(&$details, $source) {
        $result = null;
        Kernel::setRedirect($this->getLink());
        if (!$this->hasRights('delete comment')) {
            Modules::getModule('View')->addMessage($this->lang('noRightsDel'),
                    View::MSG_ERROR);
            return $result;
        }
        $this->dbdriver->delete(self::COMMENTS, '`id` = ' .
                (int) substr($details, 0, -1));
        return $result;
    }

    public function &onEditComment(&$details, $source) {
        $result = null;
        if (!$this->hasRights('edit commnet')) {
            Modules::getModule('View')->addMessage($this->lang('noRightsEdit'),
                    View::MSG_ERROR);
            return $result;
        }
        $comment = $this->commentsRecord;
        $comment['data']['id'] = $details['id'];
        $this->dbapi->refresh($comment);
        $comment['data']['title'] = $details['title'];
        $comment['data']['text'] = $details['text'];
        $this->dbapi->update($comment);
        return $result;
    }

    public function &onDeleteAll(&$details, $source) {
        $result = null;
        Kernel::setRedirect($this->getLink());
        if (!$this->hasRights('delete comment')) {
            Modules::getModule('View')->addMessage($this->lang('noRightsDel'),
                    View::MSG_ERROR);
            return $result;
        }
        $url = substr($details, 0, -1);
        $url = $url == '-' ? '' : $url;
        $this->dbdriver->delete(self::COMMENTS, '`url` = \'' .
                $this->dbdriver->escapeString($url) . '\'');
        return $result;
    }

    /**
     * Displays administration interface.
     *
     * @param mixed $param Display parameter.
     */
    private function displayAdmin($param) {
        if (!$this->hasRights('view admin')) {
            return;
        }
        if ($param == 'submenu') {
            $this->displayAdminSubmenu();
        } else {
            $this->displayAdminContent();
        }
    }

    /**
     * Displays main content of administration interface.
     * 
     */
    private function displayAdminContent() {
        $url = Modules::getModule('View')->getURL();
        if (count($url) == 1) {
            $cols = array('DISTINCT `url`');
            $orderBy = array('url');
            $pages = &$this->dbdriver->select(self::COMMENTS, $cols, '',
                    $orderBy);
            foreach ($pages as &$page) {
                $page['view'] = $this->getLink($page['url'] .
                        ($page['url'] == '' ? '-/' : '/'));
                $page['delete'] = $this->getLink($page['url'] .
                        ($page['url'] == '' ? '-/' : '/'), 'deleteAll');
            }
            $params = array('pages' => $pages);
            $this->template('pages', $params);
        } elseif (count($url) > 1) {
            $url = implode('/', array_slice($url, 1));
            $url = $url == '-' ? '' : $url;
            $params = array('filter' => '`url` = \'' .
                    $this->dbdriver->escapeString($url) . '\'');
            $comments = &$this->recordList->getList($this->commentsRecord,
                    $params);
            foreach ($comments as &$comment) {
                $comment['delete'] = $this->getLink($comment['id'] . '/',
                        'delete');
                $comment['user'] = &Modules::getModule('Users')->
                        getUser($comment['user']);
                $comment['user'] = htmlspecialchars($comment['user']['data']
                        ['login']);
            }
            $params = array('comments' => $comments, 'form' =>
                    $this->getForm('editComment', true, 'Comments'));
            $this->template('admincomments', $params);
        }
    }

    /**
     * Displays administration submenu
     *
     */
    private function displayAdminSubmenu() {
        $params = array('menu' => array(array('href' => $this->getLink(),
                'label' => $this->lang('comments'), 'title' =>
                $this->lang('commentsLinkTitle'))));
        $this->template('submenu', $params);
    }

    private function displayPublicAdmin($url) {
        $user = Modules::getModule('Users')->getUser();
        if ($user['data']['login'] == '<guest>') {
            return;
        }
        if (count($url) == 1) {
            $params = array('addCommentLink' => $this->getLink('add/'),
                    'listLink' => $this->getLink('list/'), 'postedLink' =>
                    $this->getLink('posted/'), 'myPageLink' =>
                    Config::WEB_DIR . '/visitors/' . Kernel::
                    createUrl($user['data']['login']) . '-' .
                    $user['data']['id'] . '/');
            $this->template('public-admin', $params);
        } elseif (count($url) > 1) {
            if ($url[1] == 'posted') {
                $this->displayPublicPosted($user['data']['id']);
            } elseif ($url[1] == 'list') {
                $this->displayPublicList($user['data']);
            } elseif ($url[1] == 'add') {
                $this->displayPublicAdd($user['data']);
            }
        }
    }

    private function displayPublicAdd($user) {
        $usersSrc = array_merge(Modules::getModule('Changes')->
                getUsersWhoChangedWithUser($user['id']),
                Modules::getModule('Auctions')->
                getUsersWhoPerformedSellsWithUser($user['id']));
        $users = array();
        foreach ($usersSrc as &$userSrc) {
            $userSrc = Modules::getModule('Users')->getUser($userSrc);
            $commentsURL = 'visitors/' .
                    Kernel::createUrl($userSrc['data']['login']) . '-' .
                    $userSrc['data']['id'];
            $commentsCount = $this->
                    getUsersCommentsCount($user['id'], $commentsURL);
            $completeChanges = Modules::getModule('Changes')->
                    getChangeCountBetweenUsers($user['id'],
                    $userSrc['data']['id']);
            $completeSells = Modules::getModule('Auctions')->
                    getSellsCountBetweenUsers($user['id'],
                    $userSrc['data']['id']);
            if ($commentsCount < $completeChanges + $completeSells) {
                $userSrc = $userSrc['data'];
                $userSrc['link'] = Config::WEB_DIR . '/visitors/' .
                        Kernel::createUrl($userSrc['login']) . '-' .
                        $userSrc['id'] . '/';
                $userSrc['completeChanges'] = $completeChanges +
                        $completeSells;
                $userSrc['commentsCount'] = $commentsCount;
                $users[] = $userSrc;
            }
        }
        $params = array('users' => &$users);
        $this->template('comments-add', $params);
    }

    private function displayPublicList($user) {
        $url = 'visitors/' . Kernel::createUrl($user['login']) . '-' .
                $user['id'];
        $params = array('filter' => '`url` = \''. $this->dbdriver->
                escapeString($url) . '\'', 'order' => array('!id'));
        $comments = &$this->recordList->getList($this->commentsRecord,
                $params);
        foreach ($comments as &$comment) {
            $comment['from'] = Modules::getModule('Users')->
                    getUser($comment['user']);
            $comment['fromLink'] = Config::WEB_DIR . '/visitors/' .
                    Kernel::createUrl($comment['from']['data']['login']) .
                    '-' . $comment['from']['data']['id'] . '/';
            $comment['from'] = $comment['from']['data']['login'];
        }
        $params = array('comments' => &$comments);
        $this->template('comments-list', $params);
    }

    private function displayPublicPosted($byUser) {
        $params = array('filter' => '`user` = '. (int) $byUser, 'order' =>
                array('!id'));
        $comments = &$this->recordList->getList($this->commentsRecord,
                $params);
        foreach ($comments as &$comment) {
            $comment['to'] = substr($comment['url'],
                    strrpos($comment['url'], '-') + 1);
            $comment['to'] = Modules::getModule('Users')->
                    getUser((int) $comment['to']);
            $comment['toLink'] = Config::WEB_DIR . '/visitors/' .
                    Kernel::createUrl($comment['to']['data']['login']) . '-' .
                    $comment['to']['data']['id'] . '/';
            $comment['to'] = $comment['to']['data']['login'];
        }
        $params = array('comments' => &$comments);
        $this->template('posted-comments', $params);
    }

    /**
     * Displays public user interface.
     *
     * @param mixed $param The display parameter.
     */
    private function displayPublic($param) {
        if ($param == 'user-admin') {
            $url = Modules::getModule('View')->getURL();
            if ($url[0] != 'user-admin') {
                return $this->displayPublicAdmin($url);
            }
        }
        if ($param == null) {
            $param = Modules::getModule('View')->getURL();
        }
        if (is_array($param) && isset($param['mode']) &&
                ($param['mode'] == 'custom')) {
            $this->displayPublicCustom($param);
            return;
        }
        $url = is_array($param) ? implode('/', $param) : $param;
        $param = array('filter' => '`url` = \'' .
                $this->dbdriver->escapeString($url) . '\'', 'order' => array(
                'id'));
        $comments = &$this->recordList->getList($this->commentsRecord, $param);
        foreach ($comments as &$comment) {
            $user = &Modules::getModule('Users')->
                    getUser((int) $comment['user']);
            $comment['user'] = htmlspecialchars($user['data']['login']);
        }
        $params = array('module' => $this->getName(), 'form' =>
                $this->getAddCommentForm($url), 'comments' => $comments);
        $this->template('comments', $params);
    }

    private function displayPublicCustom(&$params) {
        $allowAdding = $params['allowAdd'];
        $url = $params['url'];
        $params = array('filter' => '`url` = \'' . $this->dbdriver->
                escapeString($params['url']) . '\'', 'count' =>
                (int) $params['onPage'], 'start' => ($params['page'] - 1) *
                (int) $params['onPage'], 'order' => $params['order']);
        $pages = array('COUNT(*)');
        $pages = &$this->dbdriver->select(self::COMMENTS, $pages,
                $params['filter']);
        $pages = ceil($pages[0]['COUNT(*)'] / $params['count']);
        $pages = $pages < 1 ? 1 : $pages;
        $comments = &$this->recordList->getList($this->commentsRecord,
                $params);
        foreach ($comments as &$comment) {
            $comment['user'] = Modules::getModule('Users')->
                    getUser($comment['user']);
            $comment['userLink'] = Config::WEB_DIR . '/visitors/' .
                    Kernel::createUrl($comment['user']['data']['login']) .
                    '-' . $comment['user']['data']['id'] . '/';
            $comment['user'] = $comment['user']['data']['login'];
        }
        $user = substr($url, strrpos($url, '-') + 1);
        $user = Modules::getModule('Users')->getUser((int) $user);
        $params = array('pages' => $pages, 'page' =>
                ($params['start'] / $params['count']) + 1, 'allowAdding' =>
                $allowAdding, 'form' => $this->getAddCommentForm($url),
                'comments' => $comments, 'pageLink' => Config::WEB_DIR .
                '/visitors/' . (Kernel::createUrl($user['data']['login']) .
                '-' . $user['data']['id'] . '/'));
        $this->template('custom-comments', $params);
    }

    /**
     * Returns definition of form for adding a new comment.
     *
     * @return Array A form definiton
     */
    private function getAddCommentForm($url) {
        $cols = array('id', 'title');
        $user = Modules::getModule('Users')->getUser();
        $form = array('start' => 'addComment', 'submit' => 'addCommentBtn',
                'legend' => 'addCommentForm', 'items' => array(
                array('name' => 'title', 'label' => 'title'),
                array('name' => 'text', 'label' => 'text', 'type' =>
                'textarea', 'cols' => 50, 'rows' => 5, 'class' => 'noEditor'),
                array('name' => 'url', 'type' => 'hidden', 'value' => $url)));
        $this->prepareFormData($form);
        return $form;
    }
}
?>
